<?php if (! defined('APPPATH')) die('No direct script access allowed');
/**
 * RENARTI IK
 * An open source application development framework for PHP 5.2.0 or newer
 *
 * @package		RtiFramework
 * @author		Nauris Dambis <nauris.dambis@renarti.com>
 * @copyright	Copyright (c) 2012, RENARTI IK.
 * @license		http://renarti.com/#license
 * @link		http://renarti.com
 * @since		Version 1.0
 */

class RtiUri
{
	protected $_allowed_uri_chars = '';
	
	protected $_uri_path = '';
	
	protected $_uri_segments = array();
	
	protected $_request_method = '';
	
	protected $_routed_controller = '';

	protected $_routed_method = '';
	
	protected $_routed_key = '';
	
	protected $_routed_value = array();
	
	protected $_rules; 
	
	public function __construct()
	{
		// cache [REQUEST_METHOD]
		if (defined('CLI'))
		{
			$this->_request_method = 'cli';
		}
		else 
		{
			$this->_request_method = strtolower($_SERVER['REQUEST_METHOD']);	
		}
		
		// set route rules
		$this->_rules = Rti::config('routes')->items();
		
		// allowed URI chars
		$this->_allowed_uri_chars = str_replace(array('\-', '\\-'), array('-', '/\-'), preg_quote(Rti::config('config')->get('ALLOWED_URI_CHARS')));
	}
	
	private function _normalize_uri_path($uri)
	{
		$uri = $uri . '/';
		return str_replace('//', '/', $uri);
	}
	
	private function _get_uri_path()
	{
		return str_replace(array($_SERVER['SCRIPT_NAME'],$_SERVER['QUERY_STRING'],'?'), array('', '', ''), $_SERVER['REQUEST_URI']);
	}
	
	private function _try_route_auto()
	{
		for($i = 1; $i < count($this->_uri_segments); $i++)
		{
			$path = implode('/', array_slice($this->_uri_segments, 0, intval($i)));
			
			$basename = ucfirst($this->_uri_segments[$i]) . 'Controller';
			
			$filename = APPPATH . 'controllers' . $path . '/' . $basename . '.php';
			
			if (file_exists($filename))
			{
				$this->_routed_controller = $path . '/' . $basename;
				$this->_routed_method     = (empty($this->_uri_segments[intval($i + 1)]))? 'index' : $this->_uri_segments[intval($i + 1)];
				
				$this->_routed_key = 'auto';
				$this->_routed_value = array($this->_routed_controller, $this->_routed_method);
				
				return TRUE;
			}
		}
	}
	
	private function _try_route_rules()
	{
		// route replace patterns
		$rreplace = array(
				'(:any)'   => '(.?)*',
				'(:int)'   => '([0-9])+',
				'(:alpha)' => '([a-z])+',
			);
		
		// parse routes
		foreach ($this->_rules as $rpattern => $rvalue)
		{
			// normalize route rule 
			$_rpattern = $rpattern;
			$_rpattern = str_replace('/', '\/', $_rpattern);
			$_rpattern = str_replace(array_keys($rreplace), array_values($rreplace), $_rpattern);
			
			// check match
			if (preg_match('#^\/'. $_rpattern . '\/$#i', $this->_uri_path))
			{
				// cache route params
				$this->_routed_key   = $rpattern;
				$this->_routed_value = $rvalue;
				
				// set routed controller				
				$this->_routed_controller = $rvalue[0];
				
				// set routed method
				$this->_routed_method = 'index';
				if (isset($rvalue[1]))
				{
					$this->_routed_method = $rvalue[1];
				}
				
				// route rule was found!
				return TRUE;
			}			
		}
		
		return FALSE;
	} 
	
	private function _try_route_default()
	{
		// try set default route rule 
		if (isset($this->_rules['default']))
		{
			$this->_routed_key = 'default';
			$this->_routed_value = $this->_rules[$this->_routed_key];
			
			$this->_routed_controller = $this->_routed_value[0];
			$this->_routed_method     = 'index';
			
			// default route rule was found!
			return TRUE;
		}
		return FALSE;
	}
	
	public function requestMethod()
	{
		// [REQUEST_METHOD]
		return $this->_request_method;
	}
	
	public function routeURL()
	{
		$uri = $this->_get_uri_path();
		$this->route($uri);
	}
	
	public function route($uri)
	{
		$uri = urldecode($uri);
		
		if ($uri != '' && $this->_allowed_uri_chars != '')
		{
			if (! preg_match("#^[" . $this->_allowed_uri_chars . "]+$#i", $uri))
			{
				Rti::showError('The URI has disallowed characters.');
			}
		}
		
		// reset routed data
		$this->_routed_method     = '';
		$this->_uri_segments      = array();
		$this->_routed_controller = '';	
		$this->_routed_key        = '';
		$this->_routed_value      = array();
		
		// set last uri path
		$this->_uri_path = $this->_normalize_uri_path($uri);
		
		// split uri segments
		$this->_uri_segments = explode('/', $this->_uri_path);
		
		if ($this->_try_route_rules() === TRUE) return TRUE;
		
		if ($this->_try_route_auto() === TRUE) return TRUE;
		
		if ($this->_try_route_default() === TRUE) return TRUE;
				
		// no route rule found!!!
		Rti::show_404();
	}

	public function segments()
	{
		return $this->_uri_segments;
	}
	
	public function segment($index = 3)
	{
		return (isset($this->_uri_segments[$index]))? $this->_uri_segments[$index] : FALSE;
	}

	public function routedController()
	{
		return $this->_routed_controller;
	}
	
	public function routedMethod()
	{
		return $this->_routed_method;
	}

}


/* End of file RtiUri.php */
/* Location: ./system/core/RtiUri.php */
